﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace sqlsearcher.Models
{
    public class JsonToModel
    {
        public static string ToModel(string json)
        {
            Dictionary<string, object> data = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);

            Dictionary<string,object> objs = new Dictionary<string, object>();

            var sb = new StringBuilder();
            sb.Append($"public class Example \n");
            sb.Append("{\n");
            foreach (var item in data.Keys)
            {
                var obj = data[item];
                var typeName = GetType(obj);
                if (typeName=="?")
                {
                    typeName = typeName.Replace("?", item);
                    objs[item]=data[item].ToString();
                }
                else if (typeName == "List<?>")
                {
                    typeName = typeName.Replace("?", item);
                    objs[item] = data[item].ToString();
                }
                else if (typeName == "?[]")
                {
                    typeName = typeName.Replace("?", item);

                    var arrs=JsonConvert.DeserializeObject<List<object>>( data[item].ToString());
                    if (arrs.Count > 0)
                    {
                        typeName = typeName.Replace(item, GetType(arrs[0]));
                    }
                    if (typeName == "?[]")
                    {
                        typeName = typeName.Replace("?", item);
                        objs[item] = arrs[0].ToString();
                    }
                }
                sb.Append("\tpublic " + typeName + " " + item + " { get ; set; }\n");
            }
            sb.Append("}\n");

            foreach (var item in objs.Keys)
            {
                sb.Append(GetObject(item,objs[item]));
            }
           
            return sb.ToString();
        }
       

        private static string GetObject(string name,object value)
        {
            Dictionary<string, object> data = JsonConvert.DeserializeObject<Dictionary<string, object>>(value.ToString());

            Dictionary<string, object> objs = new Dictionary<string, object>();

            var sb = new StringBuilder();
            sb.Append($"public class {name} \n");
            sb.Append("{\n");
            foreach (var item in data.Keys)
            {
                var obj = data[item];
                var typeName = GetType(obj);
                if (typeName == "?")
                {
                    typeName = typeName.Replace("?", item);
                    objs[item] = data[item];
                }
                else if (typeName == "List<?>")
                {
                    typeName = typeName.Replace("?", item);
                    objs[item] = data[item];
                }
                else if (typeName == "?[]")
                {
                    typeName = typeName.Replace("?", item);

                    var arrs = JsonConvert.DeserializeObject<List<object>>(data[item].ToString());
                    if (arrs.Count > 0)
                    {
                        typeName = typeName.Replace(item, GetType(arrs[0]));
                    }
                    if (typeName == "?[]")
                    {
                        typeName = typeName.Replace("?", item);
                        objs[item] = arrs[0].ToString();
                    }
                }
                sb.Append("\tpublic " + typeName + " " + item + " { get ; set; }\n");
            }
            sb.Append("}\n");

            foreach (var item in objs.Keys)
            {
                sb.Append(GetObject(item, objs[item]));
            }

            return sb.ToString();
        }

        private static string GetType(object value)
        {
            var typeRes = "string";
            var typeName = value.GetType().Name;
            switch (typeName)
            {
                case "String":
                    typeRes = "string";
                    break;
                case "Int32":
                    typeRes = "int";
                    break;
                case "Int64":
                    if (value != null && int.TryParse(value.ToString(), out _))
                    {
                        typeRes = "int";
                    }
                    else
                    {
                        typeRes = "long";
                    }
                    break;
                case "Double":
                    typeRes = "double";
                    break;
                case "Decimal":
                    typeRes = "decimal";
                    break;
                case "Single":
                    typeRes = "float";
                    break;
                case "DateTime":
                    typeRes = "float";
                    break;
                case "String[]":
                    typeRes = "string[]";
                    break;
                case "Int32[]":
                    typeRes = "int[]";
                    break;
                case "List`1":
                    typeRes = "List<?>";
                    break;
                case "JArray":
                    typeRes = "?[]";
                    break;
                default:
                    typeRes = "?";
                    break;
            }
            return typeRes;
        }
    }
}